#pragma once

#include <sys/epoll.h>
#include <functional>
#include <iostream>

class EventLoop;
using callback = std::function<void()>;

// 封装了对某个套接字fd进行关心事件和监听到的事件，提供了对某种事件的添加和移除操作，以及对事件发生后的处理
class Channel {
public:
    Channel(int fd, EventLoop* loop);
    // UNDERSTAND:
    void SetReadCallback(const callback cb);
    void SetWriteCallback(const callback cb);
    void SetCloseCallback(const callback cb);
    void SetErrorCallback(const callback cb);
    void SetRevents(uint64_t revents);
    void SetState(const int state);
    // EPOLLIN / EPOLLOUT
    // 是否可读写
    bool ReadAble();
    bool WriteAble();

    // 打开可读写
    void EnableRead();
    void EnableWrite();

    // 关闭可读写
    void DisableRead();
    void DisableWrite();
    void DisableAll();

    void Update();

    // loop中删除当前channel
    void Remove();

    void HandleEvent();

    int Fd();
    uint32_t Events();
    EventLoop* OwnerLoop();
    int State();

    ~Channel();

private:
    int fd_;
    uint32_t events_;
    uint32_t revents_;
    EventLoop* loop_;
    int state_;

    callback read_callback_;
    callback write_callback_;
    callback close_callback_;
    callback error_callback_;
};
